<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta name="author" content="Cheresting" />
  <!-- 自动添加dayjs到全局 -->
  <script src="./publicJs/dayjs.min.js"></script>
  <!-- 自动添加vue到全局 -->
  <script src="./publicJs/vue.global.prod.js"></script>
  <!-- 自动添加axios到全局 -->
  <script src="./publicJs/axios.min.js"></script>
  <!-- 自动添加Cookies到全局 -->
  <script src="./publicJs/js.cookie.min.js"></script>
  <!-- 自动添加XLSX到全局 -->
  <script src="./publicJs/xlsx.core.min.js"></script>

  <link rel="stylesheet" href="./publicJs/element-plus.index.css" />
  <!-- 自动添加ElementPlus到全局 -->
  <script src="./publicJs/element-plus.index.full.js"></script>
  <script src="./publicJs/index.iife.min.js"></script>
  <!-- 添加组件到全局 -->
  <script src="./components/production-order-info.js"></script>
  <script src="./components/production-process-info.js"></script>
  <script src="./components/production-bom-info.js"></script>
  <!-- 中文化 -->
  <script src='./publicJs/zh-cn.js'></script>
  <title>安东报警记录</title>
</head>

<body>
  <div id="app">

    <el-row>
      &nbsp;
      <div class="block">
          <el-date-picker editable="false" v-model="value1" type="daterange" start-placeholder="创建时间"
            end-placeholder="结束时间" format="YYYY/MM/DD" 
            value-format="YYYY/MM/DD" />

      </div>
      &nbsp;&nbsp;&nbsp;
      <span class="custom-tabs-label">
        <el-button type="primary" @click="bjxxBtnClick">
          <el-icon>
            <Search />
          </el-icon>
          <span>查询报警信息</span>
        </el-button>
        <el-button type="success" @click="bjjlBtnClick">
          <el-icon>
            <Search />
          </el-icon>
          <span>查询报警记录</span>
        </el-button>
        <el-button type="info" @click="InfoDownload">
          <el-icon>
            <upload-filled />
          </el-icon>
          <span>导出</span>
        </el-button>
        <!-- <el-button type="info" @click="showv1">
          <span>看日期</span>
        </el-button> -->

      </span>

    </el-row>

    
    <el-table-v2 
      v-loading="bjxxloading"
      element-loading-text="Loading..."
      element-loading-background="rgba(122, 122, 122, 0.8)"
      :data="filteredBjxx" 
      :columns="col1" 
      :width="850" 
      :height="tableHeight1" 
      border 
      stripe 
      fixed  
      v-if="activeName=='bjxx'">
      </el-table-v2>
      
      <el-table-v2
        v-loading="bjjlloading"
        element-loading-text="Loading..."
        element-loading-background="rgba(122, 122, 122, 0.8)"
        :data="filteredBjjl"
        :columns="col2"
        :width="1350"
        :height="tableHeight2"
        fixed
        stripe
        v-if="activeName === 'bjjl'"
      >
    </el-table-v2>  
  </div>
</body>
<script type="module">
  import useMyXlsx from './hooks/useMyXlsx.js'
  // import zhCn from './publicJs/zh-cn.js'
  let myXlsx = useMyXlsx()
  import { showSuccess, showWarning } from './hooks/useMyMessageBox.js'
  import myAxios from './myAxios/myAxios.js'
  const { UploadFilled, Search,Calendar,Warning,CaretTop,Filter } = ElementPlusIconsVue
  const { ElImage, ElLoading,ElTag,ElButton,zhCn,ElIcon, ElPopover, ElCheckbox, ElCheckboxGroup,  } = ElementPlus
  const { createApp, ref, reactive, computed, h ,onMounted } = Vue
  
  const app = createApp({
    name: 'ExcelUploader',
    components: {
      UploadFilled,
      Search,
      // ElConfigProvider,
    }
    ,
    setup() {
      const activeName = ref('')
      const value1 = ref('')
      const data = ref([''])
      const col1=ref([''])
      const bjjlloading=ref(true)
      const bjxxloading=ref(true)

      const HEADER_HEIGHT = 50; 
      const ROW_HEIGHT_ESTIMATE = 50; 
      const MAX_HEIGHT = window.innerHeight - 50; 
      const tableHeight1 = computed(() => {
        const contentHeight = HEADER_HEIGHT + (filteredBjxx.value.length * ROW_HEIGHT_ESTIMATE);
        return Math.min(contentHeight, MAX_HEIGHT);
      });
      const tableHeight2 = computed(() => {
        const contentHeight = HEADER_HEIGHT + (filteredBjjl.value.length * ROW_HEIGHT_ESTIMATE);
        return Math.min(contentHeight, MAX_HEIGHT);
      });

      col1.value=[ 
              {
                dataKey: 'SNAME',
                title: '装置IP',
                width: 300,
                align: 'center',
                fixed: 'left',
                headerCellRenderer: () => {
                  return h('div', {
                    style: {
                      display: 'inline-flex',
                      alignItems: 'center',
                      justifyContent: 'center',
                      width: '100%',
                      height: '100%'
                    }
                  }, [
                    // 文本：装置IP
                    h('span', { style: { marginRight: '4px' } }, '装置IP'),

                    // 筛选图标 + Popover
                    h(ElPopover, {
                      ref: popoverRef, 
                      trigger: 'click',
                      width: 220,
                      persistent: true,
                      'onUpdate:visible': (visible) => {
                    
                      }
                    }, {
                      // 点击的图标
                      reference: () => h(ElIcon, {
                        style: { marginLeft: '4px', cursor: 'pointer' },
                        class: 'hover:text-primary'
                      }, { default: () => h(Filter) }),

                      // Popover 内容
                      default: () => h('div', { class: 'p-2' }, [
                        // 多选框组
                        h(ElCheckboxGroup, {
                          modelValue: selectedIPs.value,
                          'onUpdate:modelValue': (val) => {
                            selectedIPs.value = val
                          },
                          style: {
                            display: 'flex',
                            flexDirection: 'column',
                            gap: '8px',
                            padding: '4px 0'
                          }
                        }, () => fixedIPs.value.map(ip => 
                          h(ElCheckbox, { label: ip.value, key: ip.value }, () => ip.label)
                        )),

                        // 按钮
                        h('div', {
                          style: {
                            display: 'flex',
                            justifyContent: 'end',
                            gap: '8px',
                            marginTop: '12px',
                            paddingTop: '8px',
                            borderTop: '1px solid #eee'
                          }
                        }, [
                          h(ElButton, {
                            size: 'small',
                            text: true,
                            onClick: () => {
                              
                              onReset()
                            }
                          }, () => '重置'),

                          h(ElButton, {
                            size: 'small',
                            type: 'primary',
                            onClick: () => {
                              
                              onFilter()
                            }
                          }, () => '确定')
                        ])
                      ])
                    })
                  ])
                }
              },
            {
              dataKey: 'SDATE',
              title: '报警时间',
              width: 200,
              align: 'center',
            },
            {
              dataKey: 'SRESULT',
              title: '报警信息',
              width: 340,
              align: 'center',
            },
          
          ]
      
      const col2 = [
      
      {
        key: 'CREATE_TIME',
        title: '创建时间',
        dataKey: 'CREATE_TIME',
        width: 200,
      },
      {
        key: 'STATE',
        title: '状态',
        dataKey: 'STATE',
        width: 100,
        headerCellRenderer: () => {
          return h('div', {
            style: {
              display: 'inline-flex',
              alignItems: 'center',
              justifyContent: 'center',
              width: '100%',
              height: '100%'
            }
          }, [
            // 表头文字
            h('span', { style: { marginRight: '4px' } }, '状态'),

            // 筛选图标 + Popover
            h(ElPopover, {
              ref: popoverStateRef,
              trigger: 'click',
              width: 220,
              persistent: true
            }, {
              // 图标
              reference: () => h(ElIcon, {
                style: { marginLeft: '4px', cursor: 'pointer' },
                class: 'hover:text-primary'
              }, { default: () => h(Filter) }),

              // Popover 内容
              default: () => h('div', { class: 'p-2' }, [
                // 多选框组
                h(ElCheckboxGroup, {
                  modelValue: selectedStates.value,
                  'onUpdate:modelValue': (val) => {
                    selectedStates.value = val
                  },
                  style: {
                    display: 'flex',
                    flexDirection: 'column',
                    gap: '8px',
                    padding: '4px 0'
                  }
                }, () => stateOptions.map(option =>
                  h(ElCheckbox, { label: option.value, key: option.value }, () => option.label)
                )),

                // 按钮区域
                h('div', {
                  style: {
                    display: 'flex',
                    justifyContent: 'end',
                    gap: '8px',
                    marginTop: '12px',
                    paddingTop: '8px',
                    borderTop: '1px solid #eee'
                  }
                }, [
                  h(ElButton, {
                    size: 'small',
                    text: true,
                    onClick: onStateReset
                  }, () => '重置'),

                  h(ElButton, {
                    size: 'small',
                    type: 'primary',
                    onClick: onStateFilter
                  }, () => '确定')
                ])
              ])
            })
          ])
        }
      },
      {
        key: 'CONTENT',
        title: '内容',
        dataKey: 'CONTENT',
        width: 500, 
      },
      {
        key: 'DONE_TIME',
        title: '完成时间',
        dataKey: 'DONE_TIME',
        width: 200,
      },
      {
        key: 'FIRST_WORKID',
        title: '一级处理',
        dataKey: 'FIRST_WORKID',
        width: 100,
      },
      {
        key: 'SECOND_WORKID',
        title: '二级处理',
        dataKey: 'SECOND_WORKID',
        width: 100,
      },
      {
        key: 'PATH',
        title: '图片',
        dataKey: 'PATH',
        width: 100,
        // 使用 cellRenderer 自定义单元格内容
        cellRenderer: ({ cellData: path }) => {
          // cellData 是当前行该列的数据
          if (path) {
            return h(ElImage, {
              style: { width: '100px', height: '100px' },
              src: path,
              showProgress: true,
              previewSrcList: [path],
              fit: 'cover',
              previewTeleported: true,
            });
          }
          return h('span', '无图片');
        },
      },
    ];
      let bjjlExportOption_bomSum = {
        titles: {
          'ID': 'ID',
          'CONTENT': '内容',
          'STATE': '状态',
          'CREATE_TIME': '创建时间',
          'DONE_TIME': '完成时间',
          'FIRST_WORKID': '一级处理',
          'SECOND_WORKID': '二级处理',
          'PATH': '图片',
        },
        header: ['ID', 'CONTENT', 'STATE', 'CREATE_TIME', 'DONE_TIME', 'FIRST_WORKID', 'SECOND_WORKID', 'PATH'],
        // hideColumns: ['']
      };
      let bjxxExportOption_bomSum = {
        titles: {
          'SNAME': '装置IP',
          'SDATE': '报警时间',
          'SRESULT': '报警信息',
        },
        header: ['SNAME', 'SDATE', 'SRESULT'],
        // hideColumns: ['']
      };

      const errorLogData = ref([''])
      const errorInfoData = ref([''])
      const bjxx = ref([''])
      const bjjl = ref([''])
      // 状态映射表
      const STATUS_MAP = {
        64: "手环绿灯",
        32: "手环黄灯",
        16: "手环红灯",
        8: "呼叫主管",
        4: "品质异常",
        2: "设备异常",
        1: "物料短缺"
      };
      // 将 ISO 时间字符串格式化为 'YYYY/MM/DD HH:mm:ss'
      const formatDateString = (isoString) => {
        const date = new Date(isoString);
        // 检查日期是否有效
        if (isNaN(date.getTime())) {
          console.warn(`Invalid date string: ${isoString}`);
          return isoString; 
        }
        // console.warn(`date${date}`);
        const year = date.getFullYear();
        // 月份从0开始，所以需要+1，并补零
        const month = String(date.getMonth() + 1).padStart(2, '0');
        const day = String(date.getDate()).padStart(2, '0');
        const hours = String(date.getHours()).padStart(2, '0');
        const minutes = String(date.getMinutes()).padStart(2, '0');
        const seconds = String(date.getSeconds()).padStart(2, '0');

        return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
      };
      // 将状态码转换为对应的描述数组
      const getStatusDescriptions = (code) => {
        const descriptions = [];
        // 按位检查，从高位到低位
        for (const [value, description] of Object.entries(STATUS_MAP).sort((a, b) => b[0] - a[0])) {
          const numericValue = parseInt(value, 10);
          if (code & numericValue) {
            descriptions.push(description);
          }
        }
        return descriptions;
      };

      // 处理数据的主要函数
      const processWorkerStatus = (res, errorInfoData) => {
        // 按 SNAME 分组数据
        const groupedData = {};
        res.forEach(item => {
          if (!groupedData[item.SNAME]) {
            groupedData[item.SNAME] = [];
          }
          groupedData[item.SNAME].push(item);
        });

        const result = [];

        // 遍历每个分组
        for (const [sname, items] of Object.entries(groupedData)) {

          // 用于存储上一条记录的解析后的状态数组
          let previousStatusCodes = [];

          // 遍历排序后的每条记录
          items.forEach((item, index) => {
            const currentSDATA = item.SDATA;
            const currentDate = item.SDATE;

            // 将当前 SDATA 按每两位分割并转换为十进制数组
            const currentStatusCodes = [];
            for (let i = 0; i < currentSDATA.length; i += 2) {
              const hexPair = currentSDATA.substring(i, i + 2);
              // 确保是有效的十六进制字符串
              if (/^[0-9A-Fa-f]{2}$/.test(hexPair)) {
                currentStatusCodes.push(parseInt(hexPair, 16));
              } else {
                // 如果不是有效十六进制，可以推入0或根据需要处理
                console.warn(`Invalid hex pair '${hexPair}' in SDATA for SNAME: ${sname}, SDATE: ${currentDate}`);
                currentStatusCodes.push(0);
              }
            }

            // 如果是第一条记录，则没有 previousStatusCodes，跳过差值计算
            if (index === 0) {
              previousStatusCodes = currentStatusCodes;
              return; // continue to next item
            }

            // 计算差值并生成结果
            for (let i = 0; i < currentStatusCodes.length; i++) {
              const diff = currentStatusCodes[i] - previousStatusCodes[i];
              const absDiff = Math.abs(diff);

              // 检查差值是否对应单一状态或可分解的状态组合
              const descriptions = getStatusDescriptions(absDiff);

              if (descriptions.length > 0) {
                const action = diff >= 0 ? '新增' : '解除';
                const workstation = i + 1; // 工位号从1开始
                const descriptionStr = descriptions.join(',');
                // 格式化日期
                const formattedDate = formatDateString(currentDate);
                result.push({
                  SNAME: sname,
                  SDATE: formattedDate,
                  SRESULT: `工位 ${workstation}：${action}[${descriptionStr}]`
                });
              }
            }

            // 更新 previousStatusCodes 为当前记录的状态
            previousStatusCodes = currentStatusCodes;
          });
        }

        // 将结果赋值给 errorInfoData.value
        errorInfoData.value = result;
      };

      //日期筛选
      const filterErrorInfoByDateRange = (errorData, dateRange, targetRef) => {
        // 确保 dateRange 有效且包含两个元素
        if (!Array.isArray(dateRange) || dateRange.length < 2) {
          // console.warn("Invalid date range provided.");
          targetRef.value = [];
          return false;
        }

        const startDateStr = dateRange[0];
        const endDateStr = dateRange[1];

        // 简单验证日期字符串格式 (基本检查)
        const dateRegex = /^\d{4}\/\d{2}\/\d{2}$/;
        if (!dateRegex.test(startDateStr) || !dateRegex.test(endDateStr)) {
          console.warn("Invalid date format in date range. Expected YYYY/MM/DD.");
          targetRef.value = [];
          return false;
        }

        // 筛选逻辑
        let filteredData = errorData.filter(item => {
          // 使用 let 声明变量，因为它会被重新赋值
          let itemDateStr = '';

          // 确定要使用的日期字段
          if (item.SDATE != null && typeof item.SDATE === 'string') {
            itemDateStr = item.SDATE;
          } else if (item.CREATE_TIME != null && typeof item.CREATE_TIME === 'string') {
            itemDateStr = item.CREATE_TIME;
          } else {
            // 如果两个字段都不存在或都不是字符串，则跳过该项
            // console.log("Skipping item with no valid date:", item); 
            return false;
          }

          // 检查获取到的日期字符串是否有效且长度足够
          if (itemDateStr.length < 10) {
            console.warn("Date string too short in item:", item);
            return false;
          }

          //  提取 'YYYY/MM/DD' 部分进行比较 
          const itemDatePart = itemDateStr.substring(0, 10);

          // 直接字符串比较日期部分
          return itemDatePart >= startDateStr && itemDatePart <= endDateStr;
        });
        // 根据实际的日期时间字符串 (SDATE 或 CREATE_TIME) 进行升序排序
        filteredData.sort((a, b) => {
          // 为 a 和 b 获取日期字符串
          const getDateStr = (item) => {
            if (item.SDATE != null && typeof item.SDATE === 'string') {
              return item.SDATE;
            } else if (item.CREATE_TIME != null && typeof item.CREATE_TIME === 'string') {
              return item.CREATE_TIME;
            }
            
            return ''; 
          };

          const dateA = getDateStr(a);
          const dateB = getDateStr(b);

          // 使用字符串比较进行排序 
          if (dateA < dateB) {
            return -1;
          }
          if (dateA > dateB) {
            return 1;
          }
          return 0; // 相等
          // return dateA < dateB ? -1 : dateA > dateB ? 1 : 0;
        });
        // 将筛选并排序后的结果赋值给目标引用
        targetRef.value = filteredData;
        return true;
      };

      const FErrorInfoData = ref([]);
      const FErrorLogData = ref([]);
      const showv1 = () => {
        showWarning(value1.value[0] + ' >>> ' + value1.value[1])
        console.log('dateInfo', value1.value)
      }

      const Download = (data, ExportOption_bomSum) => {
        myXlsx.exportDatas(
          data.value, ExportOption_bomSum
        )
      }
      const bjxxDownload = () => {
        Download(filteredBjxx, bjxxExportOption_bomSum)
      }
      const bjjlDownload = () => {
        Download(filteredBjjl, bjjlExportOption_bomSum)
      }
      const InfoDownload = () => {
        if (activeName.value == 'bjxx')
          bjxxDownload();
        else if (activeName.value == 'bjjl')
          bjjlDownload();
      }
      let getTableDatas = function () {
        let params = ''
        let name = '丁允鑫查询安东报警记录'
        myAxios
          .get(name, params, 'Q902')
          .then((res) => {
            if (res instanceof Array) {
              errorLogData.value = res
              
              // showSuccess('最新报警记录获取成功!')
            } else {
              showWarning('获取数据失败res!' + res)
            }
            bjjlloading.value = false
          })
          .catch((err) => {
            bjjlloading.value = false
            showWarning('获取数据失败err!' + err)
          })
      }
      getTableDatas()



      let getbjxx = function () {
        let params = ''
        let name = '丁允鑫查询安东报警信息'
        myAxios
          .get(name, params, 'Q902')
          .then((res) => {
            if (res instanceof Array) {

              processWorkerStatus(res, errorInfoData);
              // console.log("处理前：",res,"处理后：",errorInfoData.value);
              // showSuccess('最新报警信息获取成功!')
            } else {
              showWarning('获取数据失败res!' + res)
            }
            bjxxloading.value = false
          })
          .catch((err) => {
            bjxxloading.value = false
            showWarning('获取数据失败err!' + err)
          })
      }
      getbjxx();
      // 提取所有唯一的 IP 地址
      const fixedIPs =ref([]);
      let getSname = function () {
        let params = ''
        let name = '丁允鑫查询安东报警SNAME'
        myAxios
          .get(name, params, 'Q902')
          .then((res) => {
            if (res instanceof Array) {

              fixedIPs.value = res.map(item => ({
                label: item.SNAME,
                value: item.SNAME
              }));
              // console.log("fps",fixedIPs.value)
             

            } else {
              showWarning('获取数据失败res!' + res)
            }
            bjxxloading.value = false
          })
          .catch((err) => {
            bjxxloading.value = false
            
            showWarning('获取数据失败err!' + err)
          })
      }
      getSname();
      

      const selectedIPs = ref([]) // 选中的 IPs
      const shouldFilter = ref(false) // 是否启用筛选
      //  过滤函数
      const popoverRef = ref()
      const onFilter = () => {
        shouldFilter.value = true
        if (popoverRef.value?.hide) {
          popoverRef.value.hide()
        }
      }
      onFilter();
      const onReset = () => {
        selectedIPs.value = []
        shouldFilter.value = false
        if (popoverRef.value?.hide) {
          popoverRef.value.hide()
        }
      }
      let bjxxBtnClick = function () {
        activeName.value = 'bjxx'
        if (filterErrorInfoByDateRange(errorInfoData.value, value1.value, FErrorInfoData) != false) {
          bjxx.value = FErrorInfoData.value
        }
        else
          bjxx.value = errorInfoData.value
      }
      let bjjlBtnClick = function () {
        activeName.value = 'bjjl'
        if (filterErrorInfoByDateRange(errorLogData.value, value1.value, FErrorLogData) != false)
          bjjl.value = FErrorLogData.value
        else
          bjjl.value = errorLogData.value
      }
      errorInfoData.value = [
        {
          SNAME: '测试172.18.37.101',
          SDATE: '测试2025/08/06',
          SDATA: '4848484848484848484848480000',

        },
      ]

      errorLogData.value = [
        {
          id: '测试',
          content: '测试',
          status: '测试',
          creTime: '测试a',
          comTime: '测试',
          firDeal: '测试',
          secDeal: '测试',
          pic: 'http://htqdds.haitian.com:9911/QDMES/CHER/driver_tpx_system/imgs/123ca808-5593-4365-ba4c-1dd267fd36e6.jpg',
        },

      ]



      const filteredBjxx = computed(() => {
        if (!shouldFilter.value || selectedIPs.value.length === 0) {
          return bjxx.value // 返回原始数据
        }
        return bjxx.value.filter(row => selectedIPs.value.includes(row.SNAME))
      })


      const stateOptions = [
        { label: '仓库已处理', value: '仓库已处理' },
        { label: '未处理', value: '未处理' },
        { label: '一级处理', value: '一级处理' },
        { label: '二级处理', value: '二级处理' }
      ]
      const selectedStates = ref([])   
      const shouldFilterState = ref(false)     
      // Popover 引用
      const popoverStateRef = ref()
      const onStateFilter = () => {
        shouldFilterState.value = true
        if (popoverStateRef.value?.hide) {
          popoverStateRef.value.hide()
        }
      }
      onStateFilter();
      const onStateReset = () => {
        selectedStates.value = []
        shouldFilterState.value = false
        if (popoverStateRef.value?.hide) {
          popoverStateRef.value.hide()
        }
      }


      const filteredBjjl = computed(() => {
        if (!shouldFilterState.value || selectedStates.value.length === 0) {
          return bjjl.value
        }
        return bjjl.value.filter(row => selectedStates.value.includes(row.STATE))
      })

      return {
        data,
        bjjlloading,
        bjxxloading,
        col1,
        col2,
        value1,
        activeName,
        errorInfoData,
        errorLogData,
        showv1,
        getTableDatas,
        getbjxx,
        bjxxBtnClick,
        bjjlBtnClick,
        processWorkerStatus,
        filteredBjxx,
        InfoDownload,
        bjxx,
        bjjl,
        zhCn,
        filteredBjxx,
        filteredBjjl,
        onStateReset,
        onStateFilter,
        selectedStates,
        shouldFilter,
        selectedIPs,
        shouldFilter,
        onFilter,
        onReset,
        popoverStateRef,
        fixedIPs,
        tableHeight1,
        tableHeight2,
      }



    },
  })

  // 使用Element Plus和中文
  app.use(ElementPlus, {
    locale: ElementPlusLocaleZhCn,
  })
  app.mount('#app')
</script>
<style scoped>
  .demo-tabs>.el-tabs__content {
    padding: 32px;
    color: #6b778c;
    font-size: 32px;
    font-weight: 600;
  }

  .demo-tabs .custom-tabs-label .el-icon {
    vertical-align: middle;
  }

  .demo-tabs .custom-tabs-label span {
    vertical-align: middle;
    margin-left: 4px;
  }

</style>

</html>